package com.slz3.business.generator;

import com.slz3.business.BusinessRouter;
import com.slz3.business.frame.util.HumpToUnderline;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;

/**
 * @auhtor buerjun
 * @date 2018-11-02
 * @desc 生成angular项目功能
 */
public class AngularTemplateGenerator {

    //对应BusinessRouter中的路由常量
    private static final String STATIC_FIELD = "CON_SHARE_MANAGE";

    //生成菜单的必要条件
    private static final String DESC = "内容管理 - 分享管理";

    //项目根路径,根据自己的项目进行修改 ,切记
    private static final String ROOT_PATH = "/Users/jieli/project/mishang-business-angular/";

    static final Path SOURCE = Paths.get(
            ROOT_PATH + "src/app/module/template-example/tem-style1");

    private static String MENU_NAME = DESC.split(" - ")[1];

    private static String TARGET_CHILD_DIC;
    private static String angularPath;

    static {

        try {
            Field field = BusinessRouter.class.getDeclaredField(STATIC_FIELD);
            BusinessRouter router = BusinessRouter.class.newInstance();
            field.setAccessible(true);
            TARGET_CHILD_DIC = field.get(router).toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        angularPath = HumpToUnderline.convert(TARGET_CHILD_DIC);
    }

    static String[] split = TARGET_CHILD_DIC.split("/");
    static String first = split[1];
    static String second = split[2];
    static String firstCharUpper = String.valueOf(first.charAt(0)).toUpperCase() + first.substring(1);
    static String secondCharUpper = String.valueOf(second.charAt(0)).toUpperCase() + second.substring(1);


    static final Path TARGET = Paths.get(
            ROOT_PATH + "src/app/module" + HumpToUnderline.convert(angularPath).replace("_", "-"));

    private String replaceTarToSou(String line) {

        return line.replace("TemplateExample", firstCharUpper)
                .replace("templateExample", first)
                .replace("template_example", HumpToUnderline.convert(first))
                .replace("template-example", HumpToUnderline.convert(first).replace("_", "-"))

                .replace("TemStyle1", secondCharUpper)
                .replace("temStyle1", second)
                .replace("tem_style1", HumpToUnderline.convert(second))
                .replace("tem-style1", HumpToUnderline.convert(second).replace("_", "-"))
                ;
    }

    public static void main(String[] args) throws Exception {
        new AngularTemplateGenerator().execute();
        //添加路由
        addRouter();
        //添加Service
        addService();
        // 添加providers
        addProviders();
        // 修改 src/app/frame/http-request-client目录下的http-request-url-api.ts;http-request-url-rou.ts,http-request-url.ts
        updateHttpRequestClient();
        //添加菜单, 如果不需要把此代码注释掉就行了
        addMenu();

    }

    //todo 添加菜单
    // this line is use for menu
    private static void addMenu() {
        String source = ROOT_PATH + "src/app/frame/zero3-layout-menu/zero3-layout-menu.component.ts";
        Path SOURCE_PATH = Paths.get(source);

        String replace = HumpToUnderline.convert(second).replace("_", "-");

        String insertMenu = "               {\n" +
                "                    id: '" + replace + "',\n" +
                "                    active: false,\n" +
                "                    name: '" + MENU_NAME + "',\n" +
                "                    href: UrlRou." + second + ".list,\n" +
                "                },";
        try {
            List<String> lines = Files.readAllLines(SOURCE_PATH);
            List<String> targetLines = new ArrayList<>(lines.size());
            for (int i = 0; i < lines.size(); i++) {
                String line = lines.get(i);
                if (line.contains("this line is use for menu")) {
                    targetLines.add(insertMenu);
                }
                targetLines.add(line);
            }
            //TODO 需要还原 SOURCE_PATH
            Files.write(SOURCE_PATH, targetLines);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    //TODO 修改 src/app/frame/http-request-client目录下的http-request-url-api.ts;http-request-url-rou.ts,http-request-url.ts
    private static void updateHttpRequestClient() {
        http_request_url_api();
        http_request_url_rou();
        http_request_url();
    }

    //this line is for static field, don't remove
    private static void http_request_url() {
        String source = ROOT_PATH + "src/app/frame/http-request-client/http-request-url.ts";
        Path SOURCE_PATH = Paths.get(source);

        String convert = HumpToUnderline.convert(second).toUpperCase();
        String insertStaticField = "        // " + DESC + "\n" +
                "        " + convert + ": '" + TARGET_CHILD_DIC.substring(1) + "',";
        try {
            List<String> lines = Files.readAllLines(SOURCE_PATH);
            List<String> targetLines = new ArrayList<>(lines.size());
            for (int i = 0; i < lines.size(); i++) {
                String line = lines.get(i);
                targetLines.add(line);
                if (line.contains("this line is for static field, don't remove")) {
                    targetLines.add(insertStaticField);
                }
            }
            Files.write(SOURCE_PATH, targetLines);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    // this line is use for static attr, don't remove
    private static void http_request_url_rou() {

        String source = ROOT_PATH + "src/app/frame/http-request-client/http-request-url-rou.ts";
        Path SOURCE_PATH = Paths.get(source);

        String convert = HumpToUnderline.convert(second).toUpperCase();
        String insertStaticAttr = "    static " + second + " = {\n" +
                "        add: `${HttpRequestUrl.toLine(`/${HttpRequestUrl.MM." + convert + "}/${HttpRequestUrl.FUNC.ADD}`)}`,\n" +
                "        list: `${HttpRequestUrl.toLine(`/${HttpRequestUrl.MM." + convert + "}/${HttpRequestUrl.FUNC.LIST}`)}`,\n" +
                "        modify: `${HttpRequestUrl.toLine(`/${HttpRequestUrl.MM." + convert + "}/${HttpRequestUrl.FUNC.MODIFY}`)}`,\n" +
                "        info: `${HttpRequestUrl.toLine(`/${HttpRequestUrl.MM." + convert + "}/${HttpRequestUrl.FUNC.INFO}`)}`,\n" +
                "        choice: `${HttpRequestUrl.toLine(`/${HttpRequestUrl.MM." + convert + "}/${HttpRequestUrl.FUNC.CHOICE}`)}`,\n" +
                "        report: `${HttpRequestUrl.toLine(`/${HttpRequestUrl.MM." + convert + "}/${HttpRequestUrl.FUNC.REPORT}`)}`,\n" +
                "    };";
        try {
            List<String> lines = Files.readAllLines(SOURCE_PATH);
            List<String> targetLines = new ArrayList<>(lines.size());
            for (int i = 0; i < lines.size(); i++) {
                String line = lines.get(i);
                targetLines.add(line);
                if (line.contains("this line is use for static attr, don't remove")) {
                    targetLines.add(insertStaticAttr);
                }
            }
            Files.write(SOURCE_PATH, targetLines);

        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    // this line is use for static attr, don't remove
    private static void http_request_url_api() {
        String source = ROOT_PATH + "src/app/frame/http-request-client/http-request-url-api.ts";
        Path SOURCE_PATH = Paths.get(source);

        String convert = HumpToUnderline.convert(second).toUpperCase();
        String insertStaticAttr = "    static " + second + " = {\n" +
                "        add: `${environment.apiRootIP}/${HttpRequestUrl.MM." + convert + "}/${HttpRequestUrl.FUNC.ADD}/`,\n" +
                "        delete: `${environment.apiRootIP}/${HttpRequestUrl.MM." + convert + "}/${HttpRequestUrl.FUNC.DELETE}/`,\n" +
                "        list: `${environment.apiRootIP}/${HttpRequestUrl.MM." + convert + "}/${HttpRequestUrl.FUNC.LIST}/`,\n" +
                "        modify: `${environment.apiRootIP}/${HttpRequestUrl.MM." + convert + "}/${HttpRequestUrl.FUNC.MODIFY}/`,\n" +
                "        info: `${environment.apiRootIP}/${HttpRequestUrl.MM." + convert + "}/${HttpRequestUrl.FUNC.INFO}/`,\n" +
                "        choice: `${environment.apiRootIP}/${HttpRequestUrl.MM." + convert + "}/${HttpRequestUrl.FUNC.CHOICE}/`,\n" +
                "        report: `${environment.apiRootIP}/${HttpRequestUrl.MM." + convert + "}/${HttpRequestUrl.FUNC.REPORT}/`,\n" +
                "        audit: {\n" +
                "            submit: `${environment.apiRootIP}/${HttpRequestUrl.MM." + convert + "}/${HttpRequestUrl.FUNC.AUDIT_SUBMIT}/`,\n" +
                "            audit: `${environment.apiRootIP}/${HttpRequestUrl.MM." + convert + "}/${HttpRequestUrl.FUNC.AUDIT_AUDIT}/`,\n" +
                "            reject: `${environment.apiRootIP}/${HttpRequestUrl.MM." + convert + "}/${HttpRequestUrl.FUNC.AUDIT_REJECT}/`,\n" +
                "        }\n" +
                "    };";
        try {
            List<String> lines = Files.readAllLines(SOURCE_PATH);
            List<String> targetLines = new ArrayList<>(lines.size());
            for (int i = 0; i < lines.size(); i++) {
                String line = lines.get(i);
                targetLines.add(line);
                if (line.contains("this line is use for static attr, don't remove")) {
                    targetLines.add(insertStaticAttr);
                }
            }
            Files.write(SOURCE_PATH, targetLines);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // this line is use for import service, don't remove
    // this line is for provider, don't remove
    private static void addProviders() {
        String source = ROOT_PATH + "src/app/frame/zero3-common/zero3-common.ts";
        Path SOURCE_PATH = Paths.get(source);

        String root = HumpToUnderline.convert(first).replace("_", "-");
        String replace = HumpToUnderline.convert(second).replace("_", "-");
        String insertImport = "import {" + secondCharUpper + "Service} from '../../module/" + root + "/" + replace + "/" + replace + ".service';";
        String insertService = "        " + secondCharUpper + "Service,";

        try {
            List<String> lines = Files.readAllLines(SOURCE_PATH);
            List<String> targetLines = new ArrayList<>(lines.size());
            for (int i = 0; i < lines.size(); i++) {
                String line = lines.get(i);
                targetLines.add(line);
                if (line.contains("this line is use for import service, don't remove")) {
                    targetLines.add(insertImport);
                }
                if (line.contains(" this line is for provider, don't remove")) {
                    targetLines.add(insertService);
                }
            }
            Files.write(SOURCE_PATH, targetLines);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    // this line is use for import service, don't remove
    // this line is use for static field, don't remove
    // this line is use for constructor, don't remove
    // this line is use for set, don't remove
    //todo 添加Service
    private static void addService() {

        String target = ROOT_PATH + "src/app/frame/module/services.ts";
        Path TARGET_PATH = Paths.get(target);

        String root = HumpToUnderline.convert(first).replace("_", "-");
        String replace = HumpToUnderline.convert(second).replace("_", "-");
        String insertImport = "import {" + secondCharUpper + "Service} from '../../module/" + root + "/" + replace + "/" + replace + ".service';";
        String insertStaticField = "    static " + second + ": " + secondCharUpper + "Service;";
        String insertVar = "                private " + second + "Service: " + secondCharUpper + "Service,";
        String insertSet = "        Services." + second + " = " + second + "Service;";

        try {
            List<String> lines = Files.readAllLines(TARGET_PATH);
            List<String> targetLines = new ArrayList<>(lines.size());
            for (int i = 0; i < lines.size(); i++) {
                String line = lines.get(i);
                targetLines.add(line);
                if (line.contains("this line is use for import service, don't remove")) {
                    targetLines.add(insertImport);
                }
                if (line.contains("this line is use for static field, don't remove")) {
                    targetLines.add(insertStaticField);
                }
                if (line.contains("this line is use for constructor, don't remove")) {
                    targetLines.add(insertVar);
                }
                if (line.contains("this line is use for set, don't remove")) {
                    targetLines.add(insertSet);
                }
            }
            Files.write(TARGET_PATH, targetLines);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    //todo 添加路由
    private static void addRouter() {
        String root = HumpToUnderline.convert(first).replace("_", "-");
        String replace = HumpToUnderline.convert(second).replace("_", "-");

        String route = ROOT_PATH + "src/app/module/" + root + "/" + root + "-routing.module.ts";
        String insert = "            {path: '" + replace + "', loadChildren: './" + replace + "/" + replace + ".module#" + secondCharUpper + "Module'},";
        Path REPOSITORYS_PATH = Paths.get(route);
        try {
            List<String> lines = Files.readAllLines(REPOSITORYS_PATH);
            List<String> targetLines = new ArrayList<>(lines.size());
            for (int i = 0; i < lines.size(); i++) {
                String line = lines.get(i);
                targetLines.add(line);
                if (line.contains("this line is use for generator path, don't remove")) {
                    targetLines.add(insert);
                }
            }
            Files.write(REPOSITORYS_PATH, targetLines);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public boolean execute() throws Exception {
        // 1 遍历“模板根目录”下的每一个模板文件
        Files.walkFileTree(SOURCE, new CloneTemplateToTargetFileVisitor());
        return true;
    }

    /**
     * Created by jinxing on 2017/4/9. // 1 遍历“模板根目录”下的每一个模板文件 Files.walkFileTree(file, new
     * CloneTemplateToTargetFileVisitor());
     */
    class CloneTemplateToTargetFileVisitor extends SimpleFileVisitor<Path> {

        /**
         * 2.唯一要做的就是重写 visitFile，让它来为你工作；
         **/
        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
            // 3.过滤所有来源目录文件
            if (file.toString().endsWith(".java")
                    || file.toString().endsWith(".ts")
                    || file.toString().endsWith(".html")
                    || file.toString().endsWith(".proto")
                    || file.toString().endsWith(".jsp")
                    || file.toString().endsWith(".js")
                    || file.toString().endsWith(".css")) {
                // 来源目录文件绝对路径
                String souFileAbsDir = file.toString();
                System.out.println(souFileAbsDir);
                // 目标目录文件绝对路径 // 修改跟路径 // 修改文件名
                String tarFileAbsDir = replaceTarToSou(
                        souFileAbsDir.replace(SOURCE.toString(), TARGET.toString()));
                System.out.println(tarFileAbsDir);
                // [生成]目标目录 & 文件
                Path tarFolder = Paths
                        .get(tarFileAbsDir.substring(0, tarFileAbsDir.lastIndexOf(File.separator)));
                Path tarFile = Paths.get(tarFileAbsDir);
                if (Files.notExists(tarFolder)) {
                    Files.createDirectories(tarFolder);
                }
                if (Files.notExists(tarFile)) {
                    Files.createFile(tarFile);
                    // 写入
                    try (BufferedReader reader = Files.newBufferedReader(file, StandardCharsets.UTF_8);
                         BufferedWriter writer = Files.newBufferedWriter(tarFile, StandardCharsets.UTF_8,
                                 StandardOpenOption.WRITE)) {
                        String line;
                        while ((line = reader.readLine()) != null) {
                            writer.write(replaceTarToSou(line));
                            writer.write("\n");
                        }
                    }
                }
            }
            // 4.return
            return FileVisitResult.CONTINUE;
        }
    }

}
